home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / langs / sozo2 / scsrc20.lzh / TOP.LZH / DATA.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-22  |  8.7 KB  |  358 lines

  1. /* Copyright (c) 1988,1991 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * Routines for data flow analysis of a single instruction
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18. /*
  19.  * idata
  20.  *
  21.  * For each instruction, we have some global information, as well
  22.  * as flags indicating what the instruction does with its operands.
  23.  * We need to know if each operand is set and/or referenced. If the
  24.  * instruction has side-effects not directly related to its operands,
  25.  * we need to know that as well, so "special case" code can deal with
  26.  * that as well.
  27.  */
  28. struct    idata    {
  29.  
  30.     char    iflag;        /* flags regarding the entire instruction */
  31. #define        SIDE    0x01    /* inst. has side-effects */
  32. #define        CC    0x02    /* inst. munges condition codes */
  33.  
  34.     char    op1f;        /* flags for the first and second operands */
  35.     char    op2f;
  36. #define        SET    0x01    /* operand is set */
  37. #define        REF    0x02    /* operand is referenced */
  38.  
  39. } idata[] =
  40. {
  41.     { CC,        REF,        REF|SET },    /* OR */
  42.     { CC,        REF,        REF },        /* BTST */
  43.     { 0,        REF,        SET },        /* MOVEP */
  44.     { CC,        REF,        REF|SET },    /* BCHG */
  45.     { CC,        REF,        REF|SET },    /* BCLR */
  46.     { CC,        REF,        REF|SET },    /* BSET */
  47.     { CC,        REF,        REF|SET },    /* AND */
  48.     { CC,        REF,        REF|SET },    /* SUB */
  49.     { CC,        REF,        REF|SET },    /* ADD */
  50.     { CC,        REF,        REF|SET },    /* EOR */
  51.     { CC,        REF,        REF },        /* CMP */
  52.     { CC,        REF,        SET },        /* MOVE */
  53.     { CC,        REF|SET,    0 },        /* NEGX */
  54.     { CC,        REF,        REF },        /* CHK */
  55.     { 0,        REF,        SET },        /* LEA */
  56.     { CC,        SET,        0 },        /* CLR */
  57.     { CC,        REF|SET,    0 },        /* NEG */
  58.     { CC,        REF|SET,    0 },        /* NOT */
  59.     { CC,        REF|SET,    0 },        /* NBCD */
  60.     { CC,        REF|SET,    0 },        /* SWAP */
  61.     { SIDE,        REF,        0 },        /* PEA */
  62.     { CC,        REF|SET,    0 },        /* EXT */
  63.     { SIDE,        REF,        SET },        /* MOVEM */
  64.     { CC,        REF,        0 },        /* TST */
  65.     { CC,        REF|SET,    0 },        /* TAS */
  66.     { 0,        REF,        0 },        /* TRAP */
  67.     { SIDE,        REF|SET,    REF },        /* LINK */
  68.     { SIDE,        REF|SET,    0 },        /* UNLK */
  69.     { 0,        0,        0 },        /* RESET */
  70.     { 0,        0,        0 },        /* NOP */
  71.     { CC,        REF,        0 },        /* STOP */
  72.     { SIDE|CC,    0,        0 },        /* RTE */
  73.     { SIDE,        0,        0 },        /* RTS */
  74.     { 0,        0,        0 },        /* TRAPV */
  75.     { SIDE|CC,    0,        0 },        /* RTR */
  76.     { SIDE,        REF,        0 },        /* JSR */
  77.     { 0,        REF,        0 },        /* JMP */
  78.     { CC,        REF,        REF|SET },    /* ADDQ */
  79.     { 0,        SET,        0 },        /* ST */
  80.     { CC,        REF|SET,    REF },        /* DBT */
  81.     { CC,        REF,        REF|SET },    /* SUBQ */
  82.     { 0,        SET,        0 },        /* SF */
  83.     { CC,        REF|SET,    REF },        /* DBRA (dbf) */
  84.     { 0,        SET,        0 },        /* SHI */
  85.     { CC,        REF|SET,    REF },        /* DBHI */
  86.     { 0,        SET,        0 },        /* SLS */
  87.     { CC,        REF|SET,    REF },        /* DBLS */
  88.     { 0,        SET,        0 },        /* SCC */
  89.     { CC,        REF|SET,    REF },        /* DBCC */
  90.     { 0,        SET,        0 },        /* SCS */
  91.     { CC,        REF|SET,    REF },        /* DBCS */
  92.     { 0,        SET,        0 },        /* SNE */
  93.     { CC,        REF|SET,    REF },        /* DBNE */
  94.     { 0,        SET,        0 },        /* SEQ */
  95.     { CC,        REF|SET,    REF },        /* DBEQ */
  96.     { 0,        SET,        0 },        /* SVC */
  97.     { CC,        REF|SET,    REF },        /* DBVC */
  98.     { 0,        SET,        0 },        /* SVS */
  99.     { CC,        REF|SET,    REF },        /* DBVS */
  100.     { 0,        SET,        0 },        /* SPL */
  101.     { 0,        SET,        0 },        /* SMI */
  102.     { CC,        REF|SET,    REF },        /* DBMI */
  103.     { 0,        SET,        0 },        /* SGE */
  104.     { CC,        REF|SET,    REF },        /* DBGE */
  105.     { 0,        SET,        0 },        /* SLT */
  106.     { CC,        REF|SET,    REF },        /* DBLT */
  107.     { 0,        SET,        0 },        /* SGT */
  108.     { CC,        REF|SET,    REF },        /* DBGT */
  109.     { 0,        SET,        0 },        /* SLE */
  110.     { CC,        REF|SET,    REF },        /* DBLE */
  111.     { 0,        REF,        0 },        /* BRA */
  112.     { SIDE,        REF,        0 },        /* BSR */
  113.     { 0,        REF,        0 },        /* BHI */
  114.     { 0,        REF,        0 },        /* BLS */
  115.     { 0,        REF,        0 },        /* BCC */
  116.     { 0,        REF,        0 },        /* BCS */
  117.     { 0,        REF,        0 },        /* BNE */
  118.     { 0,        REF,        0 },        /* BEQ */
  119.     { 0,        REF,        0 },        /* BVC */
  120.     { 0,        REF,        0 },        /* BVS */
  121.     { 0,        REF,        0 },        /* BPL */
  122.     { 0,        REF,        0 },        /* BMI */
  123.     { 0,        REF,        0 },        /* BGE */
  124.     { 0,        REF,        0 },        /* BLT */
  125.     { 0,        REF,        0 },        /* BGT */
  126.     { 0,        REF,        0 },        /* BLE */
  127.     { CC,        REF,        SET },        /* MOVEQ */
  128.     { CC,        REF,        REF|SET },    /* DIVU */
  129.     { CC,        REF,        REF|SET },    /* SBCD */
  130.     { CC,        REF,        REF|SET },    /* DIVS */
  131.     { CC,        REF,        REF|SET },    /* SUBX */
  132.     { CC,        REF,        REF },        /* CMPM */
  133.     { CC,        REF,        REF|SET },    /* MULU */
  134.     { CC,        REF,        REF|SET },    /* ABCD */
  135.     { 0,        REF|SET,    REF|SET },    /* EXG */
  136.     { CC,        REF,        REF|SET },    /* MULS */
  137.     { CC,        REF,        REF|SET },    /* ADDX */
  138.     { CC,        REF,        REF|SET },    /* ASR */
  139.     { CC,        REF,        REF|SET },    /* LSR */
  140.     { CC,        REF,        REF|SET },    /* ROXR */
  141.     { CC,        REF,        REF|SET },    /* ROR */
  142.     { CC,        REF,        REF|SET },    /* ASL */
  143.     { CC,        REF,        REF|SET },    /* LSL */
  144.     { CC,        REF,        REF|SET },    /* ROXL */
  145.     { CC,        REF,        REF|SET },    /* ROL */
  146.     { 0,        0,        0 },        /* DC */
  147. };
  148.  
  149. /*
  150.  * chkset(op) - check to see if operand 'op' sets a register
  151.  *
  152.  * This given operand is set by an instruction. Depending on the
  153.  * addressing mode used, this may set a register. If so, return
  154.  * an appropriate mask. This only happens with register direct
  155.  * addressing.
  156.  */
  157. int
  158. chkset(op)
  159. register struct    opnd    *op;
  160. {
  161.     switch (M(op->amode)) {
  162.  
  163.     case REG:
  164.         return RM(op->areg);
  165.     case REGI:
  166.         if (op->amode & (INC|DEC))
  167.             return RM(op->areg);
  168.         else
  169.             return 0;
  170.  
  171.     default:
  172.         return 0;
  173.     }
  174. }
  175.  
  176. /*
  177.  * chkref(op) - check to see if operand 'op' references a register
  178.  *
  179.  * Checks for register references in source or destination
  180.  * operands, since they can occur in either.
  181.  */
  182. int
  183. chkref(op, is_src)
  184. register struct    opnd    *op;
  185. register bool    is_src;        /* is the operand a source? */
  186. {
  187.     switch (M(op->amode)) {
  188.  
  189.     case NONE:
  190.     case IMM:
  191.     case ABS:
  192.     case PCD:
  193.         return 0;
  194.  
  195.     case REG:
  196.         if (is_src)
  197.             return RM(op->areg);
  198.         else
  199.             return 0;
  200.  
  201.     case REGI:
  202.     case REGID:
  203.         return RM(op->areg);
  204.  
  205.     case REGIDX:
  206.         return (RM(op->areg) | RM(op->ireg));
  207.  
  208.     case PCDX:
  209.         return RM(op->ireg);
  210.  
  211.     default:
  212.         fprintf(stderr, "illegal mode in chkref() %d\n", M(op->amode));
  213.         exit(1);
  214.     }
  215. }
  216.  
  217. /*
  218.  * chkside(ip, type) - check for side-effects of 'ip'
  219.  *
  220.  * Return a mask of registers set or referenced (depending on 'type')
  221.  * by the given instruction. For example, "pea" sets and references
  222.  * the stack pointer.
  223.  */
  224. int
  225. chkside(ip, type)
  226. INST    *ip;
  227. int    type;
  228. {
  229.     switch (ip->opcode) {
  230.     case PEA:        /* refs/sets the stack pointer */
  231.         return RM(SP);
  232.  
  233.     case LINK:        /* refs/sets SP */
  234.         return RM(SP);
  235.  
  236.     case UNLK:
  237.         if (type == SET)
  238.             return RM(SP);
  239.         else
  240.             return 0;
  241.  
  242.     case RTE:
  243.     case RTS:
  244.     case RTR:
  245.         if (type == SET)
  246.             return RM(SP);
  247.         else
  248.             return RM(SP)|RM(D0);    /* return value's in D0 */
  249.  
  250.     case JSR:
  251.     case BSR:
  252.         /*
  253.          * We have to account, here, for what the called
  254.          * routine might do. Registers D0-3 and A0-3 may
  255.          * be munged.
  256.          */
  257.         if (type == SET)
  258.             return    RM(A0)|RM(A1)|RM(A2)|
  259.                 RM(D0)|RM(D1)|RM(D2)|RM(SP);
  260.         else
  261.             return    RM(SP);
  262.  
  263.  
  264.     case MOVEM:
  265.         /*
  266.          * We should really check for a register mask spec.
  267.          * here and parse it. The simple solution is to assume
  268.          * that all the registers used for register variables
  269.          * are referenced or modified.
  270.          */
  271.         return RM(A3)|RM(A4)|RM(A5)|RM(A7)|
  272.                RM(D3)|RM(D4)|RM(D5)|RM(D6)|RM(D7);
  273.  
  274.     default:
  275.         fprintf(stderr, "chkside() - unknown opcode\n");
  276.         exit(1);
  277.     }
  278. }
  279.  
  280. /*
  281.  * reg_set(ip) - return mask of regs set by 'ip'
  282.  */
  283. int
  284. reg_set(ip)
  285. register INST    *ip;
  286. {
  287.     int    mask = 0;    /* build up a register mask */
  288.  
  289.     if (idata[ip->opcode].op1f & SET)
  290.         mask |= chkset(&ip->src);
  291.     if (idata[ip->opcode].op1f & REF) {
  292.         if ((ip->src.amode & (INC|DEC)) != 0)
  293.             mask |= RM(ip->src.areg);
  294.     }
  295.  
  296.     if (idata[ip->opcode].op2f & SET)
  297.         mask |= chkset(&ip->dst);
  298.     if (idata[ip->opcode].op2f & REF) {
  299.         if ((ip->dst.amode & (INC|DEC)) != 0)
  300.             mask |= RM(ip->dst.areg);
  301.     }
  302.  
  303.     if (idata[ip->opcode].iflag & SIDE)
  304.         mask |= chkside(ip, SET);
  305.  
  306.     return mask;
  307. }
  308.  
  309. /*
  310.  * reg_ref(ip) - return mask of regs referenced by 'ip'
  311.  */
  312. int
  313. reg_ref(ip)
  314. register INST    *ip;
  315. {
  316.     int    mask = 0;    /* build up a register mask */
  317.  
  318.     mask |= chkref(&ip->src, idata[ip->opcode].op1f & REF);
  319.     mask |= chkref(&ip->dst, idata[ip->opcode].op2f & REF);
  320.     if (idata[ip->opcode].iflag & SIDE)
  321.         mask |= chkside(ip, REF);
  322.  
  323.     return mask;
  324. }
  325.  
  326. /*
  327.  * sets(ip, reg) - is 'reg' set by the instruction 'ip'?
  328.  */
  329. bool
  330. sets(ip, reg)
  331. INST    *ip;
  332. int    reg;
  333. {
  334.     return ((reg_set(ip) & RM(reg)) != 0);
  335. }
  336.  
  337. /*
  338.  * refs(ip, reg) - is 'reg' referenced by the instruction 'ip'?
  339.  */
  340. bool
  341. refs(ip, reg)
  342. INST    *ip;
  343. int    reg;
  344. {
  345.     return ((reg_ref(ip) & RM(reg)) != 0);
  346. }
  347.  
  348. /*
  349.  * uses(ip, ref) - is 'reg' used by the instruction 'ip'?
  350.  */
  351. bool
  352. uses(ip, reg)
  353. INST    *ip;
  354. int    reg;
  355. {
  356.     return sets(ip, reg) || refs(ip, reg);
  357. }
  358.